/*
	Copyright (C) 2011 Salil Bhagurkar

	This file is part of illusion

	illusion is free software: you can redistribute it and/or modify
	it under the terms of the GNU Lesser General Public License as
	published by the Free Software Foundation, either version 3 of
	the License, or (at your option) any later version.

	illusion is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU Lesser General Public License for more details.

	You should have received a copy of the GNU Lesser General Public
	License along with illusion.
	If not, see <http://www.gnu.org/licenses/>.
*/

#include <kernel/types.h>
#include <kernel/errors.h>
#include <apimod/apimod.h>


void string_init(string *str)
{
	str->length = 0;
	str->capacity = STRING_BASE_CAPACITY;
	str->value = (char *)malloc(str->capacity);
	str->value[0] = '\0';
}

/*
 * Adjust the capacity of a string to include one extra
 * character. This doubles the capacity.
 */
static void string_adjust_length(string *str)
{
	uint_t new_length = str->length + 1;
	if(new_length > str->capacity) {
		if(str->capacity * 2 > STRING_MAX_CAPACITY)
			insane(ENOSUP, "Currently not handling strings > %u\n",
					STRING_MAX_CAPACITY);
		char *new_value = (char *)malloc(str->capacity * 2);
		memory_copy(new_value, str->value, str->length + 1);
		free(str->value, str->capacity);
		str->capacity = str->capacity * 2;
		str->value = new_value;
	}
}

void string_append_char(string *str, char c)
{
	string_adjust_length(str);
	str->value[str->length - 1] = c;
	str->value[str->length] = '\0';
	str->length++;
}

void string_append(string *str, const char *cstring)
{
	while((*cstring) != '\0') {
		string_append_char(str, *cstring);
		cstring++;
	}
}

void string_init_from(string *str, const char *cstring)
{
	string_init(str);
	string_append(str, cstring);
}

string *string_new()
{
	string *str = (string *)malloc(sizeof(string));
	string_init(str);
	return str;
}

void string_deinit(string *str)
{
	free(str->value, str->capacity);
}

void string_delete(string *str)
{
	string_deinit(str);
	free(str, sizeof(string));
}
